home *** CD-ROM | disk | FTP | other *** search
/ World of Video / World of Video.iso / gfxprograms / 3dprograms / rayshade-4.0 / unapplied / multicsg < prev    next >
Text File  |  1995-02-13  |  15KB  |  578 lines

  1.  
  2. Multiple csg objects:
  3. The patches to csg.c and csg.h make it possible to have more than
  4. two objects in a CSG object. This is a little hack.
  5.  
  6. ======================= cut here ========================
  7. *** csg.h.orig    Wed Jun 17 18:06:22 1992
  8. --- csg.h    Wed Jun 17 18:08:38 1992
  9. ***************
  10. *** 34,40 ****
  11.   
  12.   typedef struct Csg {
  13.       char operator;            /* Union, Intersect, or Difference */
  14. !     struct Geom *obj1, *obj2;
  15.       int (*intmeth)();        /* Intersection method. */
  16.       Float bounds[2][3];
  17.   } Csg;
  18. --- 34,41 ----
  19.   
  20.   typedef struct Csg {
  21.       char operator;            /* Union, Intersect, or Difference */
  22. !     struct Geom *list;        /* Csg objects */
  23. !     int nobjs;            /* Number of objects in the list */
  24.       int (*intmeth)();        /* Intersection method. */
  25.       Float bounds[2][3];
  26.   } Csg;
  27. *** csg.c.orig    Wed Jun 17 17:46:54 1992
  28. --- csg.c    Wed Jun 17 18:02:01 1992
  29. ***************
  30. *** 40,46 ****
  31.   
  32.       csg = (Csg *)share_malloc(sizeof(Csg));
  33.       csg->operator = op;
  34. !     csg->obj1 = csg->obj2 = (Geom *)NULL;
  35.   
  36.   
  37.       switch(op) {
  38. --- 40,46 ----
  39.   
  40.       csg = (Csg *)share_malloc(sizeof(Csg));
  41.       csg->operator = op;
  42. !     csg->list = (Geom *)NULL;
  43.   
  44.   
  45.       switch(op) {
  46. ***************
  47. *** 82,123 ****
  48.       return csgName;
  49.   }
  50.   
  51. - csg_intersect_objs(csg, ray, hit1, hit2, mindist, dist1, dist2)
  52. - Csg *csg;
  53. - Ray *ray;
  54. - HitList *hit1, *hit2;
  55. - Float mindist, *dist1, *dist2;
  56. - {
  57. -     int operator;
  58. -     hit1->nodes = 0;
  59. -     hit2->nodes = 0;
  60. -     *dist1 = FAR_AWAY;
  61. -     *dist2 = FAR_AWAY;
  62. -     operator = csg->operator;
  63. -     if (!intersect(csg->obj1, ray, hit1, mindist, dist1) &&
  64. -         ((operator == CSG_INTERSECT) || (operator == CSG_DIFFERENCE))) {
  65. -         /*
  66. -          * Intersection and Difference cases: if you miss the first
  67. -          * object, you missed the whole thing.
  68. -          */
  69. -         return FALSE;
  70. -     }
  71. -     if (!intersect(csg->obj2, ray, hit2, mindist, dist2) &&
  72. -         ((operator == CSG_INTERSECT) ||
  73. -          (hit1->nodes == 0) && (operator == CSG_UNION))) {
  74. -         /*
  75. -          * Intersect case:  if you miss either object, you miss whole
  76. -          * Union case: if you miss both object, you miss whole
  77. -          */
  78. -         return FALSE;
  79. -     }
  80. -     return TRUE;
  81. - }
  82.   int
  83.   csg_enter_obj(hitp)
  84.   HitList *hitp;
  85. --- 82,87 ----
  86. ***************
  87. *** 130,143 ****
  88.   }
  89.   
  90.   static int
  91. ! CsgUnionInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
  92.   Ray *ray;
  93.   HitList *hit1p, *hit2p, **hitclose;
  94.   Float dist1, dist2, *distclose;
  95.   {
  96. !     Float distnext;
  97.       HitList hitnext, *hittmp;
  98.   
  99.       while (TRUE) {
  100.           if (hit2p->nodes == 0 ||
  101.               csg_enter_obj(hit2p)) {
  102. --- 94,120 ----
  103.   }
  104.   
  105.   static int
  106. ! CsgUnionInt(csg, ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
  107. ! Csg *csg;
  108.   Ray *ray;
  109.   HitList *hit1p, *hit2p, **hitclose;
  110.   Float dist1, dist2, *distclose;
  111.   {
  112. !     Float disttmp, distnext;
  113.       HitList hitnext, *hittmp;
  114. +     int sect, fl = 0;
  115.   
  116. +     if (dist1 > dist2) {
  117. +         /* swap so 1 is closest */
  118. +         disttmp = dist2;  
  119. +         dist2 = dist1;  
  120. +         dist1 = disttmp;
  121. +         hittmp = hit1p;
  122. +         hit1p = hit2p;
  123. +         hit2p = hittmp;
  124. +         fl = 1;
  125. +     }
  126.       while (TRUE) {
  127.           if (hit2p->nodes == 0 ||
  128.               csg_enter_obj(hit2p)) {
  129. ***************
  130. *** 149,156 ****
  131.           } else {
  132.               distnext = FAR_AWAY;
  133.               hitnext.nodes = 0;
  134. !             if (!intersect(hit1p->data[hit1p->nodes-1].obj,
  135. !                 ray, &hitnext, dist2+EPSILON, &distnext)) {
  136.                   /*
  137.                    * None of obj1 beyond, return hit2 (leaving)
  138.                    */
  139. --- 126,138 ----
  140.           } else {
  141.               distnext = FAR_AWAY;
  142.               hitnext.nodes = 0;
  143. !             if (fl || csg->nobjs == 1)
  144. !                 sect =  intersect(hit1p->data[hit1p->nodes-1].obj,
  145. !                     ray, &hitnext, dist2+EPSILON, &distnext);
  146. !             else
  147. !                 sect =  CsgIntersect(csg,
  148. !                     ray, &hitnext, dist2+EPSILON, &distnext);
  149. !             if (!sect) {
  150.                   /*
  151.                    * None of obj1 beyond, return hit2 (leaving)
  152.                    */
  153. ***************
  154. *** 169,174 ****
  155. --- 151,157 ----
  156.                   dist1 = dist2;
  157.                   CsgHitlistCopy(&hitnext, hit2p);
  158.                   dist2 = distnext;
  159. +                 fl ^= 1;
  160.                   /* and continue */
  161.               }
  162.           }
  163. ***************
  164. *** 176,189 ****
  165.   }
  166.   
  167.   static int
  168. ! CsgIntersectInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
  169.   Ray *ray;
  170.   HitList *hit1p, *hit2p, **hitclose;
  171.   Float dist1, dist2, *distclose;
  172.   {
  173.       HitList *hittmp, hitnext;
  174. !     Float distnext;
  175.   
  176.       while (TRUE) {
  177.           if (!csg_enter_obj(hit2p)) {
  178.               /* Ray is leaving obj2 */
  179. --- 159,185 ----
  180.   }
  181.   
  182.   static int
  183. ! CsgIntersectInt(csg, ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
  184. ! Csg *csg;
  185.   Ray *ray;
  186.   HitList *hit1p, *hit2p, **hitclose;
  187.   Float dist1, dist2, *distclose;
  188.   {
  189.       HitList *hittmp, hitnext;
  190. !     Float disttmp, distnext;
  191. !     int sect, fl = 0;
  192.   
  193. +     if (dist1 > dist2) {
  194. +         /* swap so 1 is closest */
  195. +         disttmp = dist2;  
  196. +         dist2 = dist1;  
  197. +         dist1 = disttmp;
  198. +         hittmp = hit1p;
  199. +         hit1p = hit2p;
  200. +         hit2p = hittmp;
  201. +         fl = 1;
  202. +     }
  203.       while (TRUE) {
  204.           if (!csg_enter_obj(hit2p)) {
  205.               /* Ray is leaving obj2 */
  206. ***************
  207. *** 195,202 ****
  208.           } else {
  209.               distnext = FAR_AWAY;
  210.               hitnext.nodes = 0;
  211. !             if (!intersect(hit1p->data[hit1p->nodes-1].obj,
  212. !                 ray, &hitnext, dist2+EPSILON, &distnext)) {
  213.                   /*
  214.                    * None of obj1 beyond, so return miss
  215.                    */
  216. --- 191,203 ----
  217.           } else {
  218.               distnext = FAR_AWAY;
  219.               hitnext.nodes = 0;
  220. !             if (fl || csg->nobjs == 1)
  221. !                 sect =  intersect(hit1p->data[hit1p->nodes-1].obj,
  222. !                     ray, &hitnext, dist2+EPSILON, &distnext);
  223. !             else
  224. !                 sect =  CsgIntersect(csg,
  225. !                     ray, &hitnext, dist2+EPSILON, &distnext);
  226. !             if (!sect) {
  227.                   /*
  228.                    * None of obj1 beyond, so return miss
  229.                    */
  230. ***************
  231. *** 213,218 ****
  232. --- 214,220 ----
  233.                   dist1 = dist2;
  234.                   CsgHitlistCopy(&hitnext, hit2p);
  235.                   dist2 = distnext;
  236. +                 fl ^= 1;
  237.                   /* and continue */
  238.               }
  239.           }
  240. ***************
  241. *** 220,226 ****
  242.   }
  243.   
  244.   static int
  245. ! CsgDifferenceInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
  246.   Ray *ray;
  247.   HitList *hit1p, *hit2p, **hitclose;
  248.   Float dist1, dist2, *distclose;
  249. --- 222,229 ----
  250.   }
  251.   
  252.   static int
  253. ! CsgDifferenceInt(csg, ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
  254. ! Csg *csg;
  255.   Ray *ray;
  256.   HitList *hit1p, *hit2p, **hitclose;
  257.   Float dist1, dist2, *distclose;
  258. ***************
  259. *** 227,232 ****
  260. --- 230,236 ----
  261.   {
  262.       Float distnext;
  263.       HitList hitnext;
  264. +     int sect;
  265.   
  266.       while (TRUE) {
  267.           if (dist1 < dist2) {
  268. ***************
  269. *** 240,247 ****
  270.               } else {
  271.                   distnext = FAR_AWAY;
  272.                   hitnext.nodes = 0;
  273. !                 if (!intersect(hit1p->data[hit1p->nodes-1].obj,
  274. !                     ray, &hitnext, dist2+EPSILON, &distnext)) {
  275.                       /*
  276.                        * None of obj1 beyond, so
  277.                        * return miss
  278. --- 244,256 ----
  279.               } else {
  280.                   distnext = FAR_AWAY;
  281.                   hitnext.nodes = 0;
  282. !                 if (csg->nobjs == 1)
  283. !                     sect = intersect(hit1p->data[hit1p->nodes-1].obj,
  284. !                         ray, &hitnext, dist2+EPSILON, &distnext);
  285. !                 else
  286. !                     sect = CsgIntersect(csg,
  287. !                         ray, &hitnext, dist2+EPSILON, &distnext);
  288. !                 if (!sect) {
  289.                       /*
  290.                        * None of obj1 beyond, so
  291.                        * return miss
  292. ***************
  293. *** 298,341 ****
  294.   HitList *hitlist;
  295.   Float mindist, *maxdist;
  296.   {
  297. !     Float dist1, dist2, disttmp, distclose;
  298. !     HitList hit1, hit2, *hit1p, *hit2p, *hitclose;
  299.   
  300. !     hit1p = &hit1;
  301. !     hit2p = &hit2;
  302. !     if (!csg_intersect_objs(csg, ray, hit1p, hit2p, mindist,
  303. !         &dist1, &dist2)) {
  304. !         /* missed the csg object */
  305.           return FALSE;
  306.       }
  307.   
  308. !     if ((dist1 > dist2) &&
  309. !         (csg->operator == CSG_UNION || csg->operator == CSG_INTERSECT)) {
  310. !         /* swap so 1 is closest (except in difference case) */
  311. !         disttmp = dist2;  
  312. !         dist2 = dist1;  
  313. !         dist1 = disttmp;
  314. !         hit1p = &hit2;  
  315. !         hit2p = &hit1;
  316. !     }
  317.   
  318. !     /*
  319. !      * Call appropriate intersection method.  If FALSE is return,
  320. !      * no hit of any kind was found.
  321. !      */
  322. !     if (!(*csg->intmeth)(ray, hit1p, hit2p, dist1, dist2,
  323. !         &hitclose, &distclose))
  324. !         return FALSE;
  325.   
  326. !     /*
  327. !      * At this time, the closest hit is in hitclose and
  328. !      * distclose.
  329. !      */
  330. !     if (distclose < mindist || distclose > *maxdist)
  331.           return FALSE;
  332.   
  333. !     CsgHitlistCopy(hitclose, hitlist);
  334. !     *maxdist = distclose;
  335.       return TRUE;
  336.   }
  337.   
  338. --- 307,384 ----
  339.   HitList *hitlist;
  340.   Float mindist, *maxdist;
  341.   {
  342. !     Float distcsg, distobj, distclose;
  343. !     HitList hit1, hit2, *hitclose, *hitcsgp, *hitobjp;
  344. !     int operator, nobjs;
  345. !     Geom *obj;
  346.   
  347. !     operator = csg->operator;
  348. !     hitcsgp = &hit1;
  349. !     distcsg = FAR_AWAY;
  350. !     obj = csg->list;
  351. !     hitcsgp->nodes = 0;
  352. !     if (!intersect(obj, ray, hitcsgp, mindist, &distcsg) &&
  353. !         (operator == CSG_INTERSECT || operator == CSG_DIFFERENCE)) {
  354. !         /*
  355. !          * Intersection and Difference cases: if you miss the
  356. !          * first object, you missed the whole thing.
  357. !          */
  358.           return FALSE;
  359.       }
  360.   
  361. !     hitobjp = &hit2;
  362. !     hitclose = &hit1;
  363. !     distclose = distcsg;
  364.   
  365. !         nobjs = csg->nobjs;
  366. !         csg->nobjs = 0;
  367.   
  368. !     while(++csg->nobjs < nobjs) {
  369. !         obj = obj->next;
  370. !         hitobjp->nodes = 0;
  371. !         distobj = FAR_AWAY;
  372. !         if (!intersect(obj, ray, hitobjp, mindist, &distobj)) {
  373. !             if (operator == CSG_INTERSECT) {
  374. !                 csg->nobjs = nobjs;
  375. !                 return FALSE;
  376. !             }
  377. !             if (hitcsgp->nodes == 0)
  378. !                 continue;
  379. !         }
  380. !         /*
  381. !          * Call appropriate intersection method.  If FALSE is return,
  382. !          * no hit of any kind was found.
  383. !          */
  384. !         if (!(*csg->intmeth)(csg, ray, hitcsgp, hitobjp, distcsg, distobj,
  385. !             &hitclose, &distclose) || distclose > *maxdist) {
  386. !             if (operator != CSG_UNION) {
  387. !                 csg->nobjs = nobjs;
  388. !                 return FALSE;
  389. !             }
  390. !             hitcsgp->nodes = 0;
  391. !             distcsg = FAR_AWAY;
  392. !             continue;
  393. !         }
  394. !         /*
  395. !          * At this time, the closest hit is in hitclose and
  396. !          * distclose.
  397. !          */
  398. !         distcsg = distclose;
  399. !         hitcsgp = hitclose;
  400. !         if (hitcsgp == &hit1)
  401. !             hitobjp = &hit2;
  402. !         else
  403. !             hitobjp = &hit1;
  404. !     }
  405. !     if (hitcsgp->nodes == 0 || distcsg < mindist || distcsg > *maxdist)
  406.           return FALSE;
  407.   
  408. !     CsgHitlistCopy(hitcsgp, hitlist);
  409. !     *maxdist = distcsg;
  410.       return TRUE;
  411.   }
  412.   
  413. ***************
  414. *** 355,387 ****
  415.   Csg *csg;
  416.   Float bounds[2][3];
  417.   {
  418. !     GeomComputeBounds(csg->obj1);
  419. !     GeomComputeBounds(csg->obj2);
  420.   
  421.       switch (csg->operator) {
  422.       case CSG_UNION:
  423. !         bounds[LOW][X] = min(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
  424. !         bounds[HIGH][X] = max(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
  425. !         bounds[LOW][Y] = min(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
  426. !         bounds[HIGH][Y] = max(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
  427. !         bounds[LOW][Z] = min(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
  428. !         bounds[HIGH][Z] = max(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
  429.           break;
  430.       case CSG_INTERSECT:
  431. !         bounds[LOW][X] = max(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
  432. !         bounds[HIGH][X] = min(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
  433. !         bounds[LOW][Y] = max(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
  434. !         bounds[HIGH][Y] = min(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
  435. !         bounds[LOW][Z] = max(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
  436. !         bounds[HIGH][Z] = min(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
  437.           break;
  438.       case CSG_DIFFERENCE:
  439. -         bounds[LOW][X] = csg->obj1->bounds[LOW][X];
  440. -         bounds[HIGH][X] = csg->obj1->bounds[HIGH][X];
  441. -         bounds[LOW][Y] = csg->obj1->bounds[LOW][Y];
  442. -         bounds[HIGH][Y] = csg->obj1->bounds[HIGH][Y];
  443. -         bounds[LOW][Z] = csg->obj1->bounds[LOW][Z];
  444. -         bounds[HIGH][Z] = csg->obj1->bounds[HIGH][Z];
  445.           break;
  446.       default:
  447.           RLerror(RL_ABORT, "Unknown csg operator type %d?\n",
  448. --- 398,438 ----
  449.   Csg *csg;
  450.   Float bounds[2][3];
  451.   {
  452. !     Geom *obj;
  453.   
  454. +     for (obj = csg->list; obj; obj = obj->next)
  455. +         GeomComputeBounds(obj);
  456. +   
  457. +     obj = csg->list;
  458. +     bounds[LOW][X]  = obj->bounds[LOW][X];
  459. +     bounds[HIGH][X] = obj->bounds[HIGH][X];
  460. +     bounds[LOW][Y]  = obj->bounds[LOW][Y];
  461. +     bounds[HIGH][Y] = obj->bounds[HIGH][Y];
  462. +     bounds[LOW][Z]  = obj->bounds[LOW][Z];
  463. +     bounds[HIGH][Z] = obj->bounds[HIGH][Z];
  464.       switch (csg->operator) {
  465.       case CSG_UNION:
  466. !         while (obj = obj->next) {
  467. !             bounds[LOW][X]  = min(bounds[LOW][X],  obj->bounds[LOW][X]);
  468. !             bounds[HIGH][X] = max(bounds[HIGH][X], obj->bounds[HIGH][X]);
  469. !             bounds[LOW][Y]  = min(bounds[LOW][Y],  obj->bounds[LOW][Y]);
  470. !             bounds[HIGH][Y] = max(bounds[HIGH][Y], obj->bounds[HIGH][Y]);
  471. !             bounds[LOW][Z]  = min(bounds[LOW][Z],  obj->bounds[LOW][Z]);
  472. !             bounds[HIGH][Z] = max(bounds[HIGH][Z], obj->bounds[HIGH][Z]);
  473. !         }
  474.           break;
  475.       case CSG_INTERSECT:
  476. !         while (obj = obj->next) {
  477. !             bounds[LOW][X]  = max(bounds[LOW][X],  obj->bounds[LOW][X]);
  478. !             bounds[HIGH][X] = min(bounds[HIGH][X], obj->bounds[HIGH][X]);
  479. !             bounds[LOW][Y]  = max(bounds[LOW][Y],  obj->bounds[LOW][Y]);
  480. !             bounds[HIGH][Y] = min(bounds[HIGH][Y], obj->bounds[HIGH][Y]);
  481. !             bounds[LOW][Z]  = max(bounds[LOW][Z],  obj->bounds[LOW][Z]);
  482. !             bounds[HIGH][Z] = min(bounds[HIGH][Z], obj->bounds[HIGH][Z]);
  483. !         }
  484.           break;
  485.       case CSG_DIFFERENCE:
  486.           break;
  487.       default:
  488.           RLerror(RL_ABORT, "Unknown csg operator type %d?\n",
  489. ***************
  490. *** 424,454 ****
  491.   Geom *list;
  492.   {
  493.       static int OpenAdvised = FALSE;
  494. !     /*
  495. !      * Currently, this only handles two objects.
  496. !      * Will be fixed in the future.
  497. !      * No really we promise.
  498. !      */
  499. !     if (!list || !list->next) {
  500. !         RLerror(RL_WARN, "CSG needs at least two objects.\n");
  501.           return 0;
  502.       }
  503. !     if (list->next->next) {
  504. !         RLerror(RL_WARN, "Currently, CSG only handles two objects.\n");
  505. !         return 0;
  506.       }
  507.       /*
  508.        * Things are put into lists backwards....
  509.        */
  510. !     csg->obj2 = list;
  511. !     csg->obj1 = list->next;
  512. !     if ((!csg->obj1->methods->closed || !csg->obj2->methods->closed) &&
  513. !         !OpenAdvised) {
  514. !         RLerror(RL_ADVISE,
  515. !             "Performing CSG with non-closed object(s).\n");
  516. !         OpenAdvised = TRUE;
  517.       }
  518. !     return csg->obj1->prims + csg->obj2->prims;
  519.   }
  520.   
  521.   void
  522. --- 475,517 ----
  523.   Geom *list;
  524.   {
  525.       static int OpenAdvised = FALSE;
  526. !     Geom *obj, *prev;
  527. !     int prims = 0;
  528. !      int nobjs = 0;
  529. !     if (!list) {
  530. !         RLerror(RL_WARN, "CSG needs at least one object.\n");
  531.           return 0;
  532.       }
  533. !     if (!list->next) {
  534. !         RLerror(RL_WARN, "CSG with only one object.\n");
  535.       }
  536. +     prev = (Geom *)0;
  537. +     for (obj = list; ; obj = obj->next) {
  538. +         if ((!obj->methods->closed) &&
  539. +             !OpenAdvised) {
  540. +             RLerror(RL_ADVISE,
  541. +                 "Performing CSG with non-closed object(s).\n");
  542. +             OpenAdvised = TRUE;
  543. +         }
  544. +         prims += obj->prims;
  545. +         nobjs++;
  546. +         if (!obj->next)
  547. +             break;
  548. +         prev = obj;
  549. +     }
  550.       /*
  551.        * Things are put into lists backwards....
  552. +      * To make the Difference methode work, we move the last
  553. +          * element of the list to the head.
  554.        */
  555. !     csg->list = obj;
  556. !     if (prev) {
  557. !         prev->next = 0;
  558. !         obj->next = list;
  559.       }
  560. !     csg->nobjs = nobjs;
  561. !     return prims;
  562.   }
  563.   
  564.   void
  565.